﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using ProjetCom.Model.Snake;
using ProjetCom.Vue;

namespace ProjetCom.Ctrl
{
    class CtrlSnake : CtrlTemplate
    {
        private Snake m_Snake;


        private BlockSnake m_obstacle;

        // Time
        private DateTime m_TimeLast;
        private int m_stepTime;

        public BlockSnake Obstacle
        {
            get{ return m_obstacle;}
        }

        public List<BlockSnake> ListeBlock
        {
            get { return m_Snake.ListeBlock; }
        }

        public CtrlSnake(IServiceProvider p_serviceProvider, int p_score) :
            base(p_serviceProvider, p_score)
        {
            m_Snake = new Snake();
            m_Level = new LevelSnake(p_serviceProvider, this);

            // Gestion du temps
            m_stepTime = 100;
            m_TimeLast = DateTime.Now;

            // Ajout du premier obstacle
            AddObstacle();
        }

        /// <summary>
        /// Ajoute un obstacle et écrase l'ancien
        /// </summary>
        private void AddObstacle()
        {
            Random rndNumbers = new Random();
            int x;
            int y;

            //temps qu'on a pas trouvé un block libre
            do
            {
                x = rndNumbers.Next() % 18;
                y = rndNumbers.Next() % 10;
            } while (m_Snake.ListeBlock.Exists(new Predicate<BlockSnake>(delegate(BlockSnake b) { return b.X == x && b.Y == y; })));

            m_obstacle = new BlockSnake(BlockName.Obstacle, x, y);
        }

        /// <summary>
        /// Mise a jour de snake
        /// </summary>
        /// <param name="_gameTime"></param>
        override public void Update(GameTime _gameTime)
        {
             // Soit on avance le snake, soit on fait un sleep du temps avant le prochain sleep
            if ((DateTime.Now - m_TimeLast).Milliseconds >= +m_stepTime)
            {
                m_TimeLast = DateTime.Now;
                Boolean eating = IsEating();

                if (eating)
                {
                    // Change le temps
                    m_stepTime -= (int)(m_stepTime * 0.05);

                    // Ajoute un obstacle
                    AddObstacle();

                    //Change le score
                    m_Score += 100;
                }

                    m_Snake.AvancerSnake(eating);

                    if (IsCrashed())
                    {
                        ReturnMenu = true;
                    }
            }
        }


        /// <summary>
        /// Détermine si on a mangé un obstacle
        /// </summary>
        /// <returns></returns>
        private Boolean IsEating()
        {
            return m_Snake.ListeBlock.Exists(new Predicate<BlockSnake>(delegate(BlockSnake b) { return b.X == m_obstacle.X && b.Y == m_obstacle.Y; }));
        }

        private Boolean IsCrashed()
        {
            return m_Snake.ListeBlock.Exists(new Predicate<BlockSnake>(delegate(BlockSnake b) { return b.X == m_Snake.Head.X && b.Y == m_Snake.Head.Y && m_Snake.Head != b; }));
        }

        /// <summary>
        /// Traite les évènements clavier
        /// </summary>
        override public void EventClavier()
        {
            // Get input state.
            KeyboardState keyboardState = Keyboard.GetState();

            // Mouvement
            if (keyboardState.IsKeyDown(Keys.Left) && m_Snake.LastDirection != Snake.Direction.Right)
                m_Snake.CurentDirection = Snake.Direction.Left;
            else if (keyboardState.IsKeyDown(Keys.Right) && m_Snake.LastDirection != Snake.Direction.Left)
                m_Snake.CurentDirection = Snake.Direction.Right;
            else if (keyboardState.IsKeyDown(Keys.Down) && m_Snake.LastDirection != Snake.Direction.Up)
                m_Snake.CurentDirection = Snake.Direction.Down;
            else if (keyboardState.IsKeyDown(Keys.Up) && m_Snake.LastDirection != Snake.Direction.Down)
                m_Snake.CurentDirection = Snake.Direction.Up;
        }
    }
}
